
package com.usc.nearbyus;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.io.StringWriter;
import java.nio.channels.FileLock;
import java.util.ArrayList;
import java.util.List;

import org.xmlpull.v1.XmlSerializer;

import edu.usc.imsc.icampus.client.activities.SubmitData;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.util.Xml;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class Nearbyus extends Activity implements AccelerometerListener, OnClickListener {

	private static Context Ctx;

	private final String TAG = "Nearbyus";
		
	private final int minDelayBetweenReadings = 4;  // in seconds
	long timeOfLastReading = 0;
	long numReadingsTaken = 0;
	long numReadingsSinceLastSubmit = 0;
	private final int maxDelayBtwServerSubmit = 10;  // in seconds
	long timeOfLastServerSubmit = 0;
	long numServerSubmits = 0;
	
	
	private static long XML_INSERT_OFFSET = 16;
	private ReadingsDbAdapter mDbAdapter;	
	
	private boolean triggeredAccelerometer=false;
	private boolean triggeredWifi=false;
	private boolean triggeredGPS=false;
	private Button buttonScan;
	WifiManager wifi;
	private WiFiScanReceiver receiver;

	private Button storedata;
	private Button submitData;

	private Button stopgpslogging;

	private Button strtgpslogging;

	
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        timeOfLastReading=System.currentTimeMillis();
        timeOfLastServerSubmit=System.currentTimeMillis();            
    	
        Ctx = this;
        
        strtgpslogging = (Button) findViewById(R.id.strtgpslogging);
        stopgpslogging = (Button) findViewById(R.id.stopgpslogging);
        storedata = (Button)findViewById(R.id.strdata);
		submitData = (Button) findViewById(R.id.sbmtdata);
		
		strtgpslogging.setOnClickListener(this);
		stopgpslogging.setOnClickListener(this);
		storedata.setOnClickListener(this);
		submitData.setOnClickListener(this);
		
       // getApplicationContext().startService(new Intent(getApplicationContext(),GPSLoggerService.class));
        
    }
    
    @Override
	public void onStop() {
    	super.onStop();
    	Log.d(TAG, "onStop");
	}
    
    @Override
	public void onClick(View v) {

		switch(v.getId()){
		case R.id.strtgpslogging:
			Log.d(TAG, "Start GPSLoggerService Called");
			getApplicationContext().startService(new Intent(getApplicationContext(),GPSLoggerService.class));
			break;
		case R.id.stopgpslogging:
			Log.d(TAG, "Stop GPSLoggerService Called");
			getApplicationContext().stopService(new Intent(getApplicationContext(),GPSLoggerService.class));
			break;			
		case R.id.strdata:
			storeDataOnExternalStorage();
			break;
			
		case R.id.sbmtdata:
			Intent intent = new Intent(getApplicationContext(),SubmitData.class);
			startActivity(intent);
			break;
		}

	}
       

    /**
     * This method ensures that we only enable monitoring once the user is on the move.
     */
	private void activateLoggingMechanism() { 

    	long curTime = System.currentTimeMillis();
    	long timeSinceLastReading=curTime-timeOfLastReading;
    	long timeSinceLastSubmit=curTime-timeOfLastServerSubmit;

    	Log.d(TAG , "curTime := "+curTime+" timeSinceLastReading := "+timeSinceLastReading);  	
    	
    	
    	if (timeSinceLastReading>(minDelayBetweenReadings*1000)) {

    		if (triggeredAccelerometer) {
        		// TO-DO: gps: add code to turn it on and get position
        		
        		// TO-DO: add code to check if GPS accuracy is sufficient (we need the high power version presumably)
        		// TO-DO: if so, add code to save entry. 

    			// reset the accelerometer, and wait again...
    			
    			
    			triggeredAccelerometer=false; 
                ((TextView) findViewById(R.id.x)).setText("...sensed movement...");
                
              //  getApplicationContext().startService(new Intent(getApplicationContext(),GPSLoggerService.class));

    			numReadingsTaken++;
        		numReadingsSinceLastSubmit++;
        		timeOfLastReading=curTime;
                ((TextView) findViewById(R.id.readingcount)).setText(Long.toString(numReadingsSinceLastSubmit));
    		}
    	}
    	
    	if (numReadingsSinceLastSubmit>0 && timeSinceLastSubmit>(maxDelayBtwServerSubmit*1000)) {
        	Log.d(TAG , "time trigger to submit to server...");
    		// TO-DO: add code here to submit data to server... assuming it all goes well...
 
//			(un-comment this when code is working...)
//        	numReadingsSinceLastSubmit=0;
        	timeOfLastServerSubmit=curTime;
    	}
    }

    protected void onResume() {
        super.onResume();
        Log.d(TAG , "onResume()... gonna start listening...");
        if (AccelerometerManager.isSupported()) {
            AccelerometerManager.startListening(this);
        }
    }
 
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG , "onDestroy()... gonna stop listening...");
        
        if (AccelerometerManager.isListening()) {
            AccelerometerManager.stopListening();
        }
 
    }   
 
    /**
     * onShake callback
     */
    public void onShake(float force) {
        Log.d(TAG , "Accelerometer shaken enough, so wake up next sensors (force="+force+")");
        triggeredAccelerometer=true;
        ((TextView) findViewById(R.id.x)).setText("shaken!");
    }
 
    /**
     * onAccelerationChanged callback
     */
    public void onAccelerationChanged(float x, float y, float z) {
    	// activateLoggingMechanism();
    	}

	public static Context getContext() {
		return Ctx;
	}
	
	
	private void storeDataOnExternalStorage() {

		mDbAdapter = new ReadingsDbAdapter(getApplicationContext());
		mDbAdapter.open();


		List<GeoRssItem> items = new ArrayList<GeoRssItem>();

		Cursor cur = mDbAdapter.getAllReadings();

		cur.moveToFirst();
		while (cur.isAfterLast() == false) {

			GeoRssItem geoItem = new GeoRssItem(cur.getString(1),cur.getString(2),cur.getString(3),cur.getString(4),
					cur.getString(5),cur.getString(6),cur.getString(7),cur.getString(8),cur.getString(9),cur.getString(10));

			items.add(geoItem);

			cur.moveToNext();
		}
		cur.close();

		writeXml(items);
		
		mDbAdapter.close();


	}


	private void writeXml(List<GeoRssItem> items){

		File folder = new File(Environment.getExternalStorageDirectory(), "nearbyus");
		boolean isNew = false;

		if (!folder.exists())
		{
			boolean folderCheck = folder.mkdirs();
			if(folderCheck){
				Log.d(TAG, "Directory Created");				
			}else{
				Log.d(TAG, "Directory not created");
			}
			isNew = true;
		}

		try {			

			File readingsFile = new File(folder.getPath(),"readings.xml");

			while (!readingsFile.exists())
			{
				readingsFile.createNewFile();				
				isNew = true;
			}

			if(isNew)
			{
				FileOutputStream initialWriter = new FileOutputStream(readingsFile,true);


				XmlSerializer serializer = Xml.newSerializer();
				StringWriter writer = new StringWriter();
				serializer.setOutput(writer);
				serializer.startDocument("UTF-8", false);		
				serializer.setPrefix("georss", "http://www.georss.org/georss");	
				serializer.setPrefix("gml", "http://www.opengis.net/gml");	
				serializer.startTag("", "rss");
				
				serializer.startTag("", "channel");				
				//serializer.attribute("", "link", "https://sites.google.com/site/nearbyus/");
				serializer.startTag("", "link");
				serializer.text("https://sites.google.com/site/nearbyus/");
				serializer.endTag("", "link");
				serializer.startTag("", "title");
				serializer.text("WiFi Tracking Submission from NearbyUs");
				serializer.endTag("", "title");

				for (GeoRssItem item: items){

					serializer.startTag("", "item");

					serializer.startTag("", "pubDate");
					serializer.text(item.getTimestamp());
					serializer.endTag("", "pubDate");
					

					serializer.startTag("", "title");
					serializer.text(item.getSsid());
					serializer.endTag("", "title");

					serializer.startTag("", "description");
					serializer.text("WiFi Signal Reading");
					serializer.endTag("", "description");

					//TODO - PV check the userid generation : should be unique for a user
					serializer.startTag("", "author");
					serializer.text(item.getUserid());
					serializer.endTag("", "author");
					
					serializer.startTag("", "georss:point");
					serializer.text(item.getLatitude()+" "+item.getLongitude());				
					serializer.endTag("", "georss:point");

					serializer.startTag("", "summary");
					serializer.text(item.getLevel());
					serializer.endTag("", "summary");

					//TODO - PV check the hardcoded value here
					serializer.startTag("", "georss:radius");
					serializer.text("2");
					serializer.endTag("", "georss:radius");

					serializer.startTag("", "isFlaggedByUser");
					serializer.text(item.getIsflagged());
					serializer.endTag("", "isFlaggedByUser");

					//TODO - PV check the hardcoded value here
					serializer.startTag("", "hasBeenSmoothed");
					serializer.text("false");
					serializer.endTag("", "hasBeenSmoothed");

					serializer.endTag("", "item");	


				}

				serializer.endTag("", "channel");
				serializer.endTag("", "rss");
				serializer.endDocument();				

				initialWriter.write(writer.toString().getBytes());
				initialWriter.flush();
				initialWriter.close();

			} else{

				RandomAccessFile fileAccess = new RandomAccessFile(readingsFile, "rw");
				FileLock lock = fileAccess.getChannel().lock();						

				try{

					fileAccess.seek((readingsFile.length() - Nearbyus.XML_INSERT_OFFSET));

					Log.d(TAG, "Seek position : " + fileAccess.getFilePointer() );
					byte[] buffer = new byte[100];
					fileAccess.read(buffer);
					Log.d(TAG, "What the hell did we read ? : " + new String(buffer));
					
					fileAccess.seek((readingsFile.length() - Nearbyus.XML_INSERT_OFFSET));

					XmlSerializer serializer = Xml.newSerializer();
					StringWriter writer = new StringWriter();
					serializer.setOutput(writer);

					for (GeoRssItem item: items){

						serializer.startTag("", "item");

						serializer.startTag("", "pubDate");
						serializer.text(item.getTimestamp());
						serializer.endTag("", "pubDate");

						serializer.startTag("", "title");
						serializer.text(item.getSsid());
						serializer.endTag("", "title");

						serializer.startTag("", "description");
						serializer.text("WiFi Signal Reading");
						serializer.endTag("", "description");

						//TODO - PV check the userid generation : should be unique for a user
						serializer.startTag("", "author");
						serializer.text(item.getUserid());
						serializer.endTag("", "author");

						serializer.startTag("", "georss:point");
						serializer.text(item.getLongitude()+" "+item.getLatitude());
						serializer.endTag("", "georss:point");

						serializer.startTag("", "summary");
						serializer.text(item.getLevel());
						serializer.endTag("", "summary");


						//TODO - PV check the hardcoded value here
						serializer.startTag("", "georss:radius");
						serializer.text("2");
						serializer.endTag("", "georss:radius");

						serializer.startTag("", "isFlaggedByUser");
						serializer.text(item.getIsflagged());
						serializer.endTag("", "isFlaggedByUser");

						//TODO - PV check the hardcoded value here
						serializer.startTag("", "hasBeenSmoothed");
						serializer.text("false");
						serializer.endTag("", "hasBeenSmoothed");

						serializer.endTag("", "item");		
						
					}			
				/*	
					serializer.endTag("", "channel");
					serializer.endTag("", "rss");
					
				//	serializer.text('<'+"/channel"+'>'+'<'+"/rss>");				
					char[] buf = new char[new String("</channel></rss>").length()];
					buf = ("</channel></rss>").toCharArray();
					serializer.text(buf, 0, buf.length);

					serializer.endTag("", "channel");
					serializer.endTag("", "rss");
				*/
					serializer.endDocument();

					
					// Had to manually add the last 2 tags + as serializer object would not allow me to add 
					// using the endTag [ as while appending to the file we do not start the tag ]
					fileAccess.writeBytes(writer.toString()+"</channel></rss>");

				}
				finally {
					
					try {
						
						if(lock != null){
							lock.release();
							}

						if (fileAccess != null){
							fileAccess.close();
						}
						
						

					} catch (IOException ex) {
						ex.printStackTrace();
					}
				}


			}	


		} catch (IOException e) {
			throw new RuntimeException(e);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}		
	}


}

